package com.example.demo.threadpool;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.*;

/**
 * 线程池饱和策略
 *
 * @author yunda
 * @date 2021/1/18 10:31
 */
public class RejectedExecutionTest {

    public static void main(String[] args) {
        // keepAliveTime（线程活动保持时间）：线程池的工作线程空闲后，保持存活的时间。
        // 所以， 如果任务很多，并且每个任务执行的时间比较短，可以调大时间，提高线程的利用率
        // TimeUnit（线程活动保持时间的单位）：可选的单位有天（DAYS）、小时（HOURS）、分钟 （MINUTES）、
        //毫秒（MILLISECONDS）、微秒（MICROSECONDS，千分之一毫秒）和纳秒（NANOSECONDS，千分之一微秒）
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,
                3,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingDeque<>(5),
                new ThreadFactoryBuilder().setNameFormat("thread-pool-test").build());
        // 线程池预热
        // 线程池会提前创建并启动所有基本线程（corePoolSize）
        //executor.prestartAllCoreThreads();
        // 线程池饱和策略(达到了最大线程池大小且工作队列已满)
        // AbortPolicy：直接抛出RejectedExecutionException异常（默认策略）
        // CallerRunsPolicy：在调用exector的线程中运行新的任务
        // DiscardPolicy：新提交的任务不处理，直接丢弃
        // DiscardOldestPolicy：丢弃队列里最近的一个任务，并执行当前任务
        // 可以根据应用场景需要来实现RejectedExecutionHandler接口自定义策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < 10; i++) {
            //提交任务,又返回  submit方法与execute方法不同之处在于，submit方法有返回，execute方法无返回，无法知晓任务是否执行成功
            Future<?> future = executor.submit(new Task());
        }
        System.out.println(executor.toString());
        executor.shutdown();
    }

    //自定义任务
    static class Task implements Runnable {
        private static int count = 0;
        //任务标识
        private int id = 0;

        public Task() {
            id = ++count;
        }

        @Override
        public void run() {
            try {
                //休眠3秒
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                System.err.println("线程被中断" + e.getMessage());
            }
            System.out.println(" 任务：" + id + "\t 工作线程: " + Thread.currentThread().getName() + " 执行完毕");
        }
    }

}
